package com.bolehui.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bolehui.base.constant.CacheConstants;
import com.bolehui.base.result.PageResult;
import com.bolehui.base.result.Result;
import com.bolehui.base.utils.JwtUtil;
import com.bolehui.base.utils.LogUtil;
import com.bolehui.base.utils.RedisUtil;
import com.bolehui.base.utils.SecurityUtil;
import com.bolehui.domain.dto.JobDTO;
import com.bolehui.domain.dto.UserDTO;
import com.bolehui.domain.po.JobPO;
import com.bolehui.domain.po.LoginPO;
import com.bolehui.domain.po.UserPO;
import com.bolehui.domain.vo.UserVO;
import com.bolehui.mapper.AreaMapper;
import com.bolehui.mapper.UserMapper;
import com.bolehui.service.UserService;
import com.bolehui.service.iSys.ISysConfigService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chendongjie     email:chendongjie@gz.iscas.ac.cn
 * @version 1.0
 * @ClassName UserServiceImpl
 * @Description
 * @createTime 2024/12/5 15:13
 * Copyright (C) 2021-2022 CASEEDER, All Rights Reserved.
 * 注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserPO> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysConfigService configService;

    @Override
    public Result login(UserDTO dto) {
        // 验证码校验
        // Result result = validateCaptcha(dto.getUsername(), dto.getPassword(), dto.getCode());
        // if(!Result.isSuccess(result)){
        //     return Result.fail(result.getMessage());
        // }
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(dto.getUserName(), dto.getPassword());
        authenticationToken.setDetails(dto.getUserType());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("用户名或密码错误");
        }
        // 通过userId生成Token
        LoginPO loginPO = (LoginPO) authenticate.getPrincipal();
        String id = loginPO.getUserPO().getUserId().toString();
        String jwt = JwtUtil.createJWT(id);
        // authenticate存入redis
        redisUtil.setCacheObject("login:" + id, loginPO);
        //把token响应给前端
        Map<String, String> map = new HashMap<>();
        map.put("token", jwt);
        return Result.success(map, "登录成功");
    }

    /**
     * 根据用户名查询用户信息
     *
     * @param username
     * @return
     */
    @Override
    public Result<UserPO> getUserInfoByName(String username) {
        QueryWrapper<UserPO> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", username);
        List<UserPO> userInfoList = userMapper.selectList(wrapper);
        if (userInfoList.isEmpty()) {
            return null;
        } else if (userInfoList.size() > 1) {
            return Result.fail("用户名已被使用，请重新输入");
        }
        return Result.success(userInfoList.get(0));
    }

    @Override
    public Result registered(UserDTO dto) {
        UserPO userPO = convert(dto);
        String password = userPO.getPassword();
        String encodePassword = new BCryptPasswordEncoder().encode(password);
        userPO.setPassword(encodePassword);
        userMapper.insert(userPO);
        return Result.success("注册成功");
    }

    @Override
    public Result modifyPassword(Long userId, String oldPassword, String newPassword) {
        if (userId == null) {
            return Result.fail("用户id不能为空");
        }
        if (StringUtil.isNullOrEmpty(oldPassword)) {
            return Result.fail("原密码不能为空");
        }
        if (StringUtil.isNullOrEmpty(newPassword)) {
            return Result.fail("新密码不能为空");
        }
        UserPO userPO = userMapper.selectById(userId);
        if (userPO == null) {
            return Result.fail("用户id对应的用户信息不存在");
        }
        boolean matches = new BCryptPasswordEncoder().matches(oldPassword, userPO.getPassword());
        if (matches) {
            String encodePassword = new BCryptPasswordEncoder().encode(newPassword);
            userPO.setPassword(encodePassword);
            userMapper.updateById(userPO);
        } else {
            return Result.fail("原密码不正确");
        }
        return Result.success("修改密码成功");
    }

    @Override
    public Result logout() {
        Long userId = SecurityUtil.getCurrentUserId();
        if (userId == null) {
            return Result.fail("用户id对应的用户信息不存在");
        }
        SecurityContextHolder.clearContext();
        redisUtil.deleteObject("login:" + userId);
        return Result.success("退出登录成功");
    }

    @Override
    public Result<UserVO> getUserPO(Long userId) {
        UserPO userPO = userMapper.selectById(userId);
        if (userPO == null) {
            return Result.fail("用户id对应的用户信息不存在");
        }
        // TODO 获取用户信息
//        Long fileId = userPO.getFileId();
//        FilePO filePO = uploadMapper.selectById(fileId);
//        String fileName = filePO.getFileName();
//        String imgUrl = minioUtil.preview(fileName);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userPO, userVO);
        return Result.success(userVO);
    }

    @Override
    public Result<UserVO> updateUserPO(UserVO vo, Long id) {
        // 1. 参数校验（确保id和vo不为空）
        if (id == null || id <= 0) {
            throw new IllegalArgumentException("用户ID不能为空且必须大于0");
        }
        if (vo == null) {
            throw new IllegalArgumentException("用户信息不能为空");
        }
        UserPO userPO = UserPO.builder()
                .userId(id)
                .userName(vo.getUserName())
                .phoneNumber(vo.getPhoneNumber())
                .sex(vo.getSex())
                .email(vo.getEmail()).build();
        int updatedRows = userMapper.updateById(userPO);
        if (updatedRows == 0) {
            throw new RuntimeException("用户更新失败，可能ID不存在");
        }
        return Result.success();
    }

    @Override
    public Result listUserWithPage(Integer pageNum, Integer pageSize) {
        try {
            if (ObjectUtil.isNull(pageNum)) {
                pageNum = 1;
            }
            if (ObjectUtil.isNull(pageSize)) {
                pageSize = 10;
            }
            // 开始分页
            PageHelper.startPage(pageNum, pageSize);
            // 1. 使用LambdaQueryWrapper查询所有职位状态
            List<UserPO> userPOList = userMapper.selectByNameIncludeDeleted();

            // 2. 检查查询结果
            if (userPOList.isEmpty()) {
                log.warn("用户列表为空");
                return Result.success(Collections.emptyList(), "未找到用户信息");
            }
            // 使用 Stream API 将 JobPO 转换为 JobDTO
            List<UserDTO> userDTOs = userPOList.stream()
                    .map(userPO -> toUserDTO(userPO, userMapper))
                    .collect(Collectors.toList());
            PageInfo<UserDTO> pageInfo = new PageInfo<>(userDTOs);
            // 创建 PageResult 对象
            PageResult<UserDTO> pageResult = new PageResult<>(pageInfo);
            // 3. 返回查询结果
            LogUtil.info(String.format("成功查询到 %d 条用户记录", userPOList.size()));
            return Result.success(pageResult);


        } catch (Exception e) {
            // 4. 捕获并处理异常
            log.error("查询职位状态列表异常", e);
            return Result.fail("查询职位状态列表失败，请稍后重试");
        }
    }

    @Override
    public Result open(Long id) {
        if (id == null) {
            return Result.fail("启用失败");
        }

        userMapper.open(id);
        return Result.fail("启用成功");
    }


    /**
     * 实体转换
     *
     * @param dto
     * @return
     */
    private UserPO convert(UserDTO dto) {
        UserPO userPO = new UserPO();
        BeanUtils.copyProperties(dto, userPO);
        return userPO;
    }

    /**
     * 校验验证码
     *
     * @param username 用户名
     * @param code     验证码
     * @param uuid     唯一标识
     * @return 结果
     */
    public Result validateCaptcha(String username, String code, String uuid) {
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        if (captchaEnabled) {
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + Optional.ofNullable(uuid).orElse("");
            String captcha = redisUtil.getCacheObject(verifyKey);
            if (captcha == null) {
                return Result.fail("验证码已过期");
            }
            redisUtil.deleteObject(verifyKey);
            if (!code.equalsIgnoreCase(captcha)) {
                return Result.fail("验证码错误");
            }
        }
        return Result.success();
    }

    public static UserDTO toUserDTO(UserPO userPO, UserMapper userMapper) {
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(userPO, userDTO);
        if (userPO.getStatus() == 0) {
            userDTO.setStatus("已启用");
        } else {
            userDTO.setStatus("已禁用");
        }
        return userDTO;
    }
}
